#include <iostream>
#include <queue>
#include <pthread.h>
#include "datathread.hpp"
#include "protocol.hpp"
#define PTHREAD_NUM_ 4
#define QUEUE_NUM_ 5
template <class T>
class ThreadPool
{
    typedef Datathreadpool<T> data;
public:
    ThreadPool(data* newdata)
    {
        _del = newdata;
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_empty, nullptr);
        pthread_cond_init(&_full, nullptr);
        for (size_t i = 0; i < PTHREAD_NUM_; i++)
        {
            newdata->_thread = this;
            pthread_create(_tid + i, nullptr, Start, (void *)newdata);
        }
    }
    static void* Start(void* args)
    {
        pthread_detach(pthread_self());
        data *dataargs = reinterpret_cast<data*>(args);
        while(true)
        {
            // 获取任务
            dataargs->_thread->pop(dataargs->message);
            // 处理任务
            dataargs->_thread->_handle.Cutrow(dataargs->message);
            // 完成请求并且更新
            dataargs->_thread->_handle.Upda(dataargs->message);
            // 处理完成返回newdata这个地址
            dataargs->_thread->back();
        }
        return nullptr;
    }
    void push(const T& val)
    {
        pthread_mutex_lock(&_mtx);
        while (_task.size() == QUEUE_NUM_)
            pthread_cond_wait(&_empty, &_mtx);
        _task.emplace(val);
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_full);
    }
    void pop(T& val)
    {
        pthread_mutex_lock(&_mtx);
        while(_task.empty())
            pthread_cond_wait(&_full, &_mtx);
        val = _task.front();
        _task.pop();
        pthread_mutex_unlock(&_mtx);
        pthread_cond_signal(&_empty);
    }
    data* back()
    {
        return _del;
    }
    ~ThreadPool()
    {
        pthread_cond_destroy(&_empty);
        pthread_cond_destroy(&_full);
        pthread_mutex_destroy(&_mtx);
        if(_del != nullptr)
            delete _del;
    }

private:
    Protocol<T> _handle;
    pthread_t _tid[PTHREAD_NUM_];
    pthread_cond_t _empty;
    pthread_cond_t _full;
    pthread_mutex_t _mtx;
    std::queue<T> _task;
    data *_del;
};